// serialize.hpp
// A generic serialization framework.
//
// Copyright (C) 2008  Maksim Sipos <msipos@mailc.net>
//
// This file is a part of the Ripe language project.
//
// Ripe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef R_SERIALIZE_HPP
#define R_SERIALIZE_HPP

#include "util/standard.hpp"
#include <ostream>
#include <istream>
#include "adts/string.hpp"

namespace Ripe {
  // TYPE MARKERS:
  #define M_EOF     0
  #define M_UINT32  1
  #define M_INT32   2
  #define M_UINT16  3
  #define M_INT16   4
  #define M_STRING  5
  // Should always equal to above:
  #define M_SUPPORTED_MARKER 5  

  // General unserialize error
  class ErrorUnserialize : public Exception {};

  // Thrown when asked to unserialize a wrong type
  class ErrorUnserializeType : public ErrorUnserialize {};

  // Thrown when the unserialization binary is found to be invalid.
  class ErrorInvalidSerialize : public ErrorUnserialize {};

  // Class to do unserialization
  class ISerializer {
    public:
      ISerializer(std::istream* str);

      std::istream* s;

      // Detect the coming data type. Returns one of the type markers above.
      uint16_t detect();

      // Unserializing functions
      uint32_t unserialize_uint32();
      int32_t unserialize_int32();
      uint16_t unserialize_uint16();
      int16_t unserialize_int16();
      char* unserialize_string(); // Returns a string you must duplicate if
                                  // you want to keep.

    private:
      // Expect a marker of the given type:
      void expect_marker(uint16_t m);

      // Read this many bytes and expect they exist (fail if read less bytes).
      void read_expect(void* buf, uint32_t buf_len);

      // Used in unserialization of strings:
      StringBuffer str_buffer;
      
      // Detect the future type or EOF
      void detect_future();

      // If detect_called, then this was the data type detected.
      uint16_t detect_type;
  };

  // Class to do serialization
  class OSerializer {
    public:
      OSerializer(std::ostream* str);

      std::ostream* s;

      // Serializing functions:
      void serialize(uint32_t i);
      void serialize(int32_t i);
      void serialize(uint16_t i);
      void serialize(int16_t i);
      void serialize(const char* s);

    private:
      void serialize_marker(uint16_t m);
  };
}

#endif // R_SERIALIZE_HPP
